#include "App_pool.h"

// 创建消息队列
// 文件目录，在dev/mqueue下
static char *mq_name = "/mq_pool";
// 消息队列的文件描述符
static mqd_t mq_fd;
// 线程池
static pthread_t *thread_pool;
// 线程池的数量
static int pool_num;

void *App_pool_thread(void *arg)
{
    TaskPool_t task_pool;
    // 不断的接受数据
    while (1)
    {
        int len = mq_receive(mq_fd, (char *)&task_pool, sizeof(TaskPool_t), NULL);
        // 判断是否接收到数据，如果接收到数据，则执行任务
        if (len == sizeof(TaskPool_t))
        {
            task_pool.task(task_pool.arg);
        }
    }
}

/**
 * @brief 初始化线程池
 *
 * @param thread_num 需要创建的线程数量
 */
int App_Pool_Init(int thread_num)
{
    // 创建消息队列
    struct mq_attr attr;
    attr.mq_maxmsg = 10;
    attr.mq_msgsize = sizeof(TaskPool_t);
    mq_fd = mq_open(mq_name, O_CREAT | O_RDWR, 0644, &attr);
    if (mq_fd == -1)
    {
        log_error("创建打开消息队列失败！");
        return -1;
    }
    // 启用多个线程，并用容器保存起来
    pool_num = thread_num;
    // 为thread_pool【分配内存空间
    thread_pool = malloc(sizeof(pthread_t) * pool_num);
    // 存入线程
    for (int i = 0; i < pool_num; i++)
    {
        pthread_create(thread_pool + i, NULL, App_pool_thread, NULL);
    }

    return 0;
}

/**
 * @brief 销毁线程池
 *
 */
void App_Pool_destroy(void)
{
    // 取消销毁消息队列
    mq_close(mq_fd);
    mq_unlink(mq_name);

    // 取消销毁线程池
    for (size_t i = 0; i < pool_num; i++)
    {
        pthread_cancel(thread_pool[i]);
        pthread_join(thread_pool[i], NULL);
    }

    // 释放内存
    free(thread_pool);
}

/**
 * @brief 注册任务到线程池
 *
 * @param task 注册的任务函数
 * @param arg 任务函数的参数
 * @return int 返回是否注册成功
 */
int App_Pool_registerTask(int (*task)(void *arg), void *arg)
{
    // 创建任务
    TaskPool_t task_pool = {
        .task = task,
        .arg = arg};

    // 发送任务到消息队列
    return mq_send(mq_fd, (char *)&task_pool, sizeof(TaskPool_t), 1);
}
